#!/bin/bash

# Define constants
SERVICE="xyz.openbmc_project.FanSensor"
FUNCTIONAL_INTERFACE="xyz.openbmc_project.State.Decorator.OperationalStatus"
AVAILABILITY_INTERFACE="xyz.openbmc_project.State.Decorator.Availability"

# D-Bus paths of fan rotors
FAN_PATHS=(
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN0_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN0_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN1_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN1_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN2_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN2_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN3_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN3_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN4_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN4_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN5_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN5_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN6_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN6_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN7_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN7_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN8_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN8_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN9_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD0_FAN9_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN10_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN10_TACH_OUTLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN11_TACH_INLET_SPEED_RPM"
    "/xyz/openbmc_project/sensors/fan_tach/FANBOARD1_FAN11_TACH_OUTLET_SPEED_RPM"
)

# Add event log
add_sel()
{
  MESSAGE="$*"

  busctl call \
    xyz.openbmc_project.Logging /xyz/openbmc_project/logging \
    xyz.openbmc_project.Logging.Create Create "ssa{ss}" "$MESSAGE" \
    xyz.openbmc_project.Logging.Entry.Level.Error 0 >/dev/null 2>&1
}

# Check normal fans
check_normal_fans() {
    local normal_count=0
    for path in "${FAN_PATHS[@]}"; do
        # Get properties with error handling
        functional=$(busctl get-property "$SERVICE" "$path" "$FUNCTIONAL_INTERFACE" Functional 2>/dev/null | awk '{print $2}')
        available=$(busctl get-property "$SERVICE" "$path" "$AVAILABILITY_INTERFACE" Available 2>/dev/null | awk '{print $2}')

        # Check if properties were fetched successfully
        if [[ -z "$functional" || -z "$available" ]]; then
            continue
        fi

        # Check for normal fan
        if [[ "$functional" == "true" && "$available" == "true" ]]; then
            normal_count=$((normal_count + 1))
        fi
    done
    echo $normal_count
}

# Restart fan sensor service
reload_fan_sensors() {
    echo "Reloading fan sensors..."
    if systemctl restart xyz.openbmc_project.fansensor; then
        echo "Fan sensors reloaded successfully."
    else
        echo "Failed to reload fan sensors." >&2
    fi
    sleep 30  # Wait for the service to stabilize
}

# Power off a single slot
power_off_slot(){
    local slot_number=$1
    local object_path="/xyz/openbmc_project/state/chassis${slot_number}"
    local service_name="xyz.openbmc_project.State.Chassis${slot_number}"
    local interface="xyz.openbmc_project.State.Chassis"
    local property="RequestedPowerTransition"
    local value="xyz.openbmc_project.State.Chassis.Transition.Off"
    local ret=0

    echo "AC Powering off slot $slot_number..."

    busctl set-property "$service_name" "$object_path" "$interface" "$property" s "$value"
    ret=$?

    if [ $ret -eq 0 ]; then
        echo "Slot $slot_number powered off successfully."
    else
        echo "Failed to power off slot $slot_number." >&2
        return $ret
    fi
}

# Power off all slots
power_off_all_slots() {
    # Log the event before shutting down
    local msg=""

    msg="Hosts 1 to 8 are being shut down due to the missing of more than 2 fan rotors."
    echo "${msg}"
    add_sel "${msg}"

    for slot in {1..8}; do
        power_off_slot "$slot"
    done
}

# Main logic
main() {
	local normal_count=24
	local normal_rototr_threashold=22
    # Initial check
    normal_count=$(check_normal_fans)
    echo "Initial normal fan count: $normal_count"

    if (( normal_count < normal_rototr_threashold )); then
        echo "Normal fan count below threshold. Attempting recovery..."
        normal_count=24
        reload_fan_sensors

        # Recheck after recovery
        normal_count=$(check_normal_fans)
        echo "Post-recovery normal fan count: $normal_count"

        if (( normal_count < normal_rototr_threashold )); then
            echo "Still > 2 rotors missing after reload the fan sensors. Initiating shutdown."
            power_off_all_slots
        else
            echo "Recovery successful. System is stable."
        fi
    else
        echo "System is stable. No action required."
    fi
}

main
